#!/usr/bin/python
# -*- encoding:utf-8 -*-
'''
@Author     : Alexxrhuang
@Data       : 2019.07.3
@Updatas    :
'''


from __future__ import print_function
import os
import re
import sys
import sox
import random
import itertools
import subprocess
from glob import glob
from utils.common import create_folder, logger
CURRENT_VERBOSITY = 11


def vad_core(wav_path, log_energy_threashold=50, min_event_duration=0.256, max_event_duration=sys.maxsize, max_silence=0.3, min_event_delay=0.5):
    '''vad的核心操作，主要采用框架auditok
    Github: https://github.com/amsehili/auditok.git

    Args:
        log_energy_threashold: 能量阈值
        min_event_duration：一个音频事件的最短时间; 这个值不能太大，否则在单发枪声音频可能有漏检
    '''
    try:
        shell_command = 'auditok -i %s -e %d -n %f -m %f -s %f' % (wav_path, log_energy_threashold, min_event_duration, max_event_duration, max_silence)
        with open(os.devnull, 'w') as devnull:
            time_infos = (subprocess.check_output(shell_command.split(), stderr=devnull)).decode("utf-8")
    except Exception as e:
        logger.info('wav %s, error: %s' % (wav_path, str(e)), extra={"verbosity": CURRENT_VERBOSITY})
        return []

    smooth_infos = []
    for info in time_infos.split('\n'):
        info = str(info).strip().split()
        if len(info) == 3:
            logger.info(info, extra={"verbosity": CURRENT_VERBOSITY})
            start_time = float(info[1])
            end_time = float(info[2])
            # 对于太短的两个音频事件，直接看成一个事件
            if smooth_infos != [] and start_time < smooth_infos[-1][2] + min_event_delay:
                smooth_infos[-1][2] = end_time
            else:
                smooth_infos.append([info[0], start_time, end_time])
    return smooth_infos


def vad(audio_dir, output_audio_dir, wav_list):
    '''进行vad处理

    Args:
        audio_dir：原始音频目录名，用于得到新的经过VAD处理后的音频目录
        wav_list：当前数据集的所有音频的路径
        output_audio_dir: 输出音频路径

    Returns:
        out_wav_list：当前数据集经过Vad处理后的所有音频的路径
    Notes:
        python2: max_event_duration=sys.int
    '''
    is_test = False
    if output_audio_dir.split('/')[-1] == 'test':
        is_test = True

    count = 0
    out_wav_list = []
    for wav_path in wav_list:
        logger.info(wav_path, extra={"verbosity": CURRENT_VERBOSITY})
        wav_name = wav_path.split('/')[-1]
        wav_path_affix = '/'.join(wav_path.split('/')[:-1])
        smooth_infos = vad_core(wav_path)

        # 对测试集进行切块处理
        if is_test:
            clip_infos = []
            for info in smooth_infos:
                clip_info = clip_wav(info)
            clip_infos.append(clip_info)
            smooth_infos = list(itertools.chain.from_iterable(clip_infos))

        for info in smooth_infos:
            logger.info(info, extra={"verbosity": CURRENT_VERBOSITY})
            out_wav_path = wav_path_affix + '/C' + info[0] + '-' + wav_name
            out_wav_path = re.sub(audio_dir, output_audio_dir, out_wav_path)
            transformer = sox.Transformer()
            transformer.trim(info[1], info[2])
            transformer.build(wav_path, out_wav_path)
            out_wav_list.append(out_wav_path)
            logger.info(out_wav_path, extra={"verbosity": CURRENT_VERBOSITY})
        logger.info('', extra={"verbosity": CURRENT_VERBOSITY})
        count += 1
        if count % 500 == 0:
            logger.info('Done %d|%d' % (count, len(wav_list)), extra={"verbosity": 2})
    return out_wav_list


def clip_wav(info):
    '''将音频进行切分
    '''
    chunk_num = info[0]
    start_time = info[1]
    end_time = info[2]

    # 切分大小为[base_clip, base_clip, base_clip, ..., base_clip]
    clip_low = 2
    clip_high = 10
    clip_info = []
    while True:
        clip_num = 1        # 切的音频更多些
        base_clip = random.uniform(clip_low, clip_high)

        # 如果音频不足以到下一次切割，则直接将剩下的音频全部截出
        if start_time + (clip_num+1) * base_clip > end_time:
            clip_info.append([chunk_num + str(clip_num), start_time, end_time])
            break
        else:
            clip_info.append([chunk_num + str(clip_num), start_time, start_time + clip_num * base_clip])
            start_time += clip_num * base_clip

    # 切分大小为[base_clip, base_clip*2, base_clip*3, ..., base_clip*n]
    # clip_num = 1
    # base_clip = 4
    # clip_info = []
    # while True:
    #     # 如果音频不足以到下一次切割，则直接将剩下的音频全部截出
    #     if start_time + (clip_num+1) * base_clip > end_time:
    #         clip_info.append([chunk_num + str(clip_num), start_time, end_time])
    #         break
    #     else:
    #         clip_info.append([chunk_num + str(clip_num), start_time, start_time + clip_num * base_clip])
    #         start_time += clip_num * base_clip
    #         clip_num += 1
    return clip_info


def main():
    vad('', '', '')


if __name__ == '__main__':
    main()
